/*
 * Licensed to the 南京汇海交通科技有限公司
 *
 * Copyright (c) 2025.
 * All rights reserved.
 *
 * 本软件属南京汇海交通科技有限公司所有，在未获得南京汇海交通科技有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.chframework.http.template;

import cn.hutool.core.text.StrSplitter;
import com.chframework.http.utility.HttpResponseEntity;
import com.chframework.http.utility.Placeholder;
import com.chframework.http.utility.ServiceConfigInfo;
import com.chframework.http.utility.ServiceConfigInfo.ServiceRequestConfigInfo;
import com.chframework.http.utility.ServiceConfigInfo.ParamProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class HttpClientTemplate {

    /**
     * HTTP请求模板对象
     */
    private HttpRequestTemplate httpRequestTemplate;
    /**
     * HTTP响应模板对象
     */
    private HttpResponseTemplate httpResponseTemplate;

    @Autowired
    public void setHttpRequestTemplate(HttpRequestTemplate httpRequestTemplate) {
        this.httpRequestTemplate = httpRequestTemplate;
    }

    @Autowired
    public void setHttpResponseTemplate(HttpResponseTemplate httpResponseTemplate) {
        this.httpResponseTemplate = httpResponseTemplate;
    }

    /**
     * @param serviceConfigInfo 自定义动态执行HTTP请求的参数配置信息
     * @param placeholderList   请求头与请求体中的占位符列表以及它们在运行时动态计算出来的常量值
     * @return 根据HTTP响应参数配置信息解析后得到的数据对象
     */
    public Map<String, Object> executeServiceTemplate(ServiceConfigInfo serviceConfigInfo, List<Placeholder> placeholderList) {
        if (placeholderList == null || placeholderList.size() <= 0) {
            return this.executeServiceTemplate(serviceConfigInfo);
        }
        placeholderList.removeIf(ph -> ph.getExpression() == null);
        Map<String, String> placeholderMap = placeholderList.parallelStream()
                .collect(Collectors.toMap(
                        Placeholder::getExpression,
                        Placeholder::getRuntimeValue,
                        (oldValue, newValue) -> newValue)
                );
        // 替换占位符
        ServiceRequestConfigInfo serviceRequestConfigInfo = serviceConfigInfo.getServiceRequestConfigInfo();
        this.setPlaceholder(placeholderMap, serviceRequestConfigInfo.getHeaderParamConfig());
        this.setPlaceholder(placeholderMap, serviceRequestConfigInfo.getQueryParamConfig());
        this.setPlaceholder(placeholderMap, serviceRequestConfigInfo.getFormParamConfig());
        this.setPlaceholder(placeholderMap, serviceRequestConfigInfo.getJsonParamConfig());
        // JSON报文中的占位符替换
        String jsonBody = serviceRequestConfigInfo.getRequestBody();
        for (Map.Entry<String, String> entry : placeholderMap.entrySet()) {
            jsonBody = fillPlaceHolder(jsonBody, entry.getKey(), entry.getValue());
        }
        serviceRequestConfigInfo.setRequestBody(jsonBody);

        return this.executeServiceTemplate(serviceConfigInfo);
    }

    /**
     * 执行HTTP网络服务调用模板
     *
     * @param serviceConfigInfo 自定义动态执行HTTP请求的参数配置信息
     * @return 根据HTTP响应参数配置信息解析后得到的数据对象
     */
    private Map<String, Object> executeServiceTemplate(ServiceConfigInfo serviceConfigInfo) {
        // 执行请求模板
        HttpResponseEntity httpResponseEntity = httpRequestTemplate.doRequest(serviceConfigInfo);
        // 执行响应模板
        return httpResponseTemplate.doResponse(serviceConfigInfo, httpResponseEntity);
    }

    /**
     * 填充占位符
     */
    private String fillPlaceHolder(String source, String placeholder, Object placeholderValue) {
        List<String> elementArray = StrSplitter.split(source, placeholder, false, false);
        return String.join(String.valueOf(placeholderValue), elementArray);
    }

    /**
     * 替换运行时占位符
     */
    private void setPlaceholder(Map<String, String> placeholderMap, List<ParamProperty> paramConfig) {
        for (ParamProperty paramProperty : paramConfig) {
            paramProperty.setSourceParamValue(
                    placeholderMap.containsKey(paramProperty.getSourceParamValue())
                            ? placeholderMap.get(paramProperty.getSourceParamValue())
                            : paramProperty.getSourceParamValue());
        }
    }
}
